package day28;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;

/**
 * @author ZJX
 * @version 1.0
 * @descption
 * @since 2025/11/4 19:38
 */
public class Day21 {
//    public static void main(String[] args) throws IOException {
//        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
//        PrintWriter out = new PrintWriter(System.out);
//        in.nextToken();
//        int n = (int) in.nval;
//        int[] nums = new int[n];
//        for (int i = 0; i < n; i++) {
//            nums[i] = i + 1;
//        }
//        int left = 0, right = n - 1;
//        while (right > left) {
//            out.print(nums[left] + " " + nums[right] + " ");
//            left++;
//            right--;
//        }
//        if (n % 2 == 1){
//            out.print(nums[left]);
//        }
//        out.close();
//    }

//    public static void main(String[] args) throws IOException {
//        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
//        PrintWriter out = new PrintWriter(System.out);
//        in.nextToken();
//        int n = (int) in.nval;
//        in.nextToken();
//        int m = (int) in.nval;
//        TreeSet<Integer> set = new TreeSet<>();
//        for (int i = 0; i < n + m; i++) {
//            in.nextToken();
//            set.add((int) in.nval);
//        }
//        Iterator<Integer> iterator = set.iterator();
//        if (iterator.hasNext()) {
//            out.print(iterator.next());
//            while (iterator.hasNext()) {
//                out.print(" " + iterator.next());
//            }
//        }
//        out.close();
//    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        String s = br.readLine();
        int n = s.length();
        int[][] dp = new int[n][n]; // 字符串 s 中从索引 i 到索引 j（闭区间 [i, j]）的子串的最长回文子序列长度
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                if (i == j) {
                    dp[i][j] = 1;
                } else {
                    if (s.charAt(i) == s.charAt(j)) {
                        dp[i][j] = dp[i + 1][j - 1] + 2;
                    } else {
                        dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]);
                    }
                }
            }
        }
        out.println(dp[0][n - 1]);
        out.close();
    }

    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int ret = 1;
        int[] dp = new int[n];
        Arrays.fill(dp, 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            ret = Math.max(ret, dp[i]);
        }
        return ret;
    }

    public int reverse(int x) {
        int result = 0;
        while (x != 0) {
            int digit = x % 10;
            x /= 10;
            if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && digit > 7)) {
                return 0;
            }
            if (result < Integer.MIN_VALUE / 10 || (result == Integer.MIN_VALUE / 10 && digit < -8)) {
                return 0;
            }
            result = result * 10 + digit;
        }
        return result;
    }

    public int maxSales(int[] sales) {
        int cur = sales[0];
        int max = sales[0];
        for (int i = 1; i < sales.length; i++) {
            cur = Math.max(cur + sales[i], sales[i]);
            max = Math.max(max, cur);
        }
        return max;
    }

    public int search(int[] nums, int target) {
        int n = nums.length;
        int left = 0, right = n - 1;
        while (right >= left) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            }
            if (nums[mid] >= nums[left]) {
                // 左半部分有序
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            } else {
                // 右边部分有序
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }

    public int findMin(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (right >= left) {
            int mid = left + (right - left) / 2;
            if (mid == right) {
                break;
            }
            if (nums[mid] >= nums[right]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return nums[right];
    }

    public int findPeakElement(int[] nums) {
        int n = nums.length;
        if (n == 1 || nums[0] > nums[1]) {
            return 0;
        }
        int left = 0, right = n - 1;
        while (right >= left) {
            int mid = left + (right - left) / 2;
            if (nums[mid] > nums[mid + 1]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

}

